<template>
  <div :id="id"></div>

  <!-- 1. module修改对话框 -->
  <WmcDialog
    title="修改model信息"
    :dialogVisible="dialogVisible_model"
    @close="closeDialog_model"
    @handleConfirm="handleConfirm_model"
  >
    <template #form>
      <el-form :model="curr_data.data" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="curr_data.data.label"></el-input>
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="curr_data.data.description"
            type="textarea"
          ></el-input>
        </el-form-item>
        <el-form-item label="实例化范围">
          <el-row>
            <el-col :span="11">
              <el-input v-model="curr_data.data.lowerMultiplicity"></el-input>
            </el-col>
            <el-col :span="2"> - </el-col>
            <el-col :span="11">
              <el-input v-model="curr_data.data.upperMultiplicity"></el-input>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item label="支持编译">
          <template v-for="item in curr_data.data.compileTimeType" :key="item">
            {{ item }}</template
          >
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>

  <!-- 2. container修改对话框 -->
  <WmcDialog
    title="修改container信息"
    :dialogVisible="dialogVisible_container"
    @close="closeDialog_container"
    @handleConfirm="handleConfirm_container"
  >
    <template #form>
      <el-form :model="curr_data.data" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="curr_data.data.label"></el-input>
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="curr_data.data.description"
            type="textarea"
          ></el-input>
        </el-form-item>
        <el-form-item label="实例化范围">
          <el-row>
            <el-col :span="11">
              <el-input v-model="curr_data.data.lowerMultiplicity"></el-input>
            </el-col>
            <el-col :span="2"> - </el-col>
            <el-col :span="11">
              <el-input v-model="curr_data.data.upperMultiplicity"></el-input>
            </el-col>
          </el-row>
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>
  <!-- 3.parameter修改对话框 -->
  <WmcDialog
    title="修改parameter信息"
    :dialogVisible="dialogVisible_parameter"
    @close="closeDialog_parameter"
    @handleConfirm="handleConfirm_parameter"
  >
    <template #form>
      <el-form :model="curr_data.data" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="curr_data.data.label"></el-input>
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="curr_data.data.description"
            type="textarea"
          ></el-input>
        </el-form-item>
        <el-form-item label="实例化范围">
          <el-row>
            <el-col :span="11">
              <el-input v-model="curr_data.data.lowerMultiplicity"></el-input>
            </el-col>
            <el-col :span="2"> - </el-col>
            <el-col :span="11">
              <el-input v-model="curr_data.data.upperMultiplicity"></el-input>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item label="参数类型">
          <el-select v-model="curr_data.data.parameterType" placeholder="">
            <el-option
              v-for="item in parameterType"
              :key="item"
              :value="item"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="默认值">
          <el-input
            v-model="curr_data.data.defaultValue"
            placeholder=""
          ></el-input>
        </el-form-item>
        <el-form-item label="最大值">
          <el-input v-model="curr_data.data.max" placeholder=""></el-input>
        </el-form-item>
        <el-form-item label="最小值">
          <el-input v-model="curr_data.data.min" placeholder=""></el-input>
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>

  <!-- 4.reference修改对话框 -->
  <WmcDialog
    title="修改reference信息"
    :dialogVisible="dialogVisible_reference"
    @close="closeDialog_reference"
    @handleConfirm="handleConfirm_reference"
  >
    <template #form>
      <el-form :model="curr_data.data" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="curr_data.data.label"></el-input>
        </el-form-item>
        <el-form-item label="描述">
          <el-input
            v-model="curr_data.data.description"
            type="textarea"
          ></el-input>
        </el-form-item>
        <el-form-item label="实例化范围">
          <el-row>
            <el-col :span="11">
              <el-input v-model="curr_data.data.lowerMultiplicity"></el-input>
            </el-col>
            <el-col :span="2"> - </el-col>
            <el-col :span="11">
              <el-input v-model="curr_data.data.upperMultiplicity"></el-input>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item label="参数类型">
          <el-select v-model="curr_data.data.parameterType" placeholder="">
            <el-option
              v-for="item in parameterType"
              :key="item"
              :value="item"
            ></el-option>
          </el-select>
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>

  <!-- 5.literal修改对话框 -->
  <WmcDialog
    title="修改literal信息"
    :dialogVisible="dialogVisible_literal"
    @close="closeDialog_literal"
    @handleConfirm="handleConfirm_literal"
  >
    <template #form>
      <el-form :model="curr_data.data" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="curr_data.data.label"></el-input>
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>

  <!-- 6.添加API配置参数 -->
  <WmcDialog
    title="添加API配置参数"
    :dialogVisible="dialogVisible_apiConfigDef"
    @close="closeDialog_apiConfigDef"
    @handleConfirm="handleConfirm_apiConfigDef"
  >
    <template #form>
      <el-form :model="apiConfigDef" label-width="100px">
        <el-form-item label="参数名称">
          <el-input v-model="apiConfigDef.name"></el-input>
        </el-form-item>
        <el-form-item label="API配置参数值">
          <el-input v-model="apiConfigDef.value" placeholder=""></el-input>
        </el-form-item>
      </el-form>
    </template>
  </WmcDialog>
</template>

<script lang="ts">
import { defineComponent, onMounted, PropType, ref, watch } from 'vue'
import G6, { TreeGraph } from '@antv/g6'
import { INode } from '@/render/store/configdef/types'
import { createContentMenu } from '@/render/utils/createContentMenu'
import {
  IMenuTemplate,
  contentMenuRemoveItem,
  modelMenuConfig,
  containerMenuConfig,
  parameterMenuConfig,
  parameterMenuConfig_boolean,
  parameterMenuConfig_enum,
  referenceMenuConfig,
  referenceMenuConfig_choice,
  literalMenuConfig
} from '../config/contextMenu.config'
import emitter from '@/render/utils/mitt'
import WmcDialog from '@/render/base-ui/dialog'
import { usePageDialogFormTree } from '@/render/hooks/use-page-dialog-form-tree'
import {
  addModelConfig,
  addContainerConfig,
  addParameterConfig,
  addReferenceConfig
} from '../config/addModel.config'
export default defineComponent({
  components: { WmcDialog },
  props: {
    id: {
      type: String,
      required: true
    },
    treeData: {
      type: Object as PropType<INode>,
      default: () => ({})
    }
  },
  emits: ['getTreeData', 'getApiConfigDef'],
  setup(props, { emit }) {
    let new_id = 0
    const curr_data = ref()
    let curr_data_id = '',
      parent_data_id = ''

    const parameterType = ref([
      'boolean',
      'integer',
      'enumeration',
      'float',
      'string',
      'function'
    ])
    let graph: TreeGraph
    // 1. 处理图的数据
    const data = ref(JSON.parse(JSON.stringify(props.treeData)))

    // console.log(data)
    // 2. 注册结点样式
    G6.registerNode('card-node', {
      draw(cfg: any, group: any) {
        const r = 2
        let color
        let description = '',
          data = cfg.data
        switch (data.type) {
          case 'parameter':
            color = '#67c23a'
            description += `defaultValue = ${data.defaultValue}`
            if (
              data.parameterType === 'interger' ||
              data.parameterType === 'float'
            ) {
              description = `min = ${data.min}
max = ${data.max}`
            }
            break
          case 'reference':
            color = '#e6a23c'
            break
          case 'literal':
            color = '#f56c6c'
            break
          case 'destination':
            color = '#909399'
            break
          default:
            color = '#409eff'
            description = `upperMultiplicity = ${data.upperMultiplicity}
lowerMultiplicity = ${data.lowerMultiplicity}`
        }

        const w = cfg.size[0]
        const h = cfg.size[1]
        const shape = group.addShape('rect', {
          attrs: {
            x: -w / 2,
            y: -h / 2,
            width: w, //200,
            height: h, // 60
            stroke: color,
            radius: r,
            fill: '#fff'
          },
          name: 'main-box',
          draggable: true
        })

        group.addShape('rect', {
          attrs: {
            x: -w / 2,
            y: -h / 2 - 10,
            width: w, //200,
            height: h / 2, // 60
            fill: color,
            radius: [r, r, 0, 0]
          },
          name: 'title-box',
          draggable: true
        })

        // title text
        group.addShape('text', {
          attrs: {
            textBaseline: 'top',
            x: -w / 2 + 15,
            y: -h / 2 + 4,
            lineHeight: 20,
            text: `${data.label}
(${data.type})`,
            fill: '#fff'
          },
          name: 'title'
        })
        cfg.children &&
          group.addShape('marker', {
            attrs: {
              x: w / 2,
              y: 0,
              r: 6,
              cursor: 'pointer',
              symbol: G6.Marker.collapse,
              stroke: '#666',
              lineWidth: 1,
              fill: '#fff'
            },
            name: 'collapse-icon'
          })
        group.addShape('text', {
          attrs: {
            textBaseline: 'top',
            x: -w / 2 + 8,
            y: -h / 2 + 50,
            lineHeight: 20,
            text: description,
            fill: 'rgba(0,0,0, 1)'
          },
          name: `description`
        })
        return shape
      },
      setState(name, value, item: any) {
        if (name === 'collapsed') {
          const marker = item
            .get('group')
            .find((ele: any) => ele.get('name') === 'collapse-icon')
          const icon = value ? G6.Marker.expand : G6.Marker.collapse
          marker.attr('symbol', icon)
        }
      }
    })

    // 3. 画图
    const drawGraph = () => {
      const toolbar = new G6.ToolBar({
        position: { x: 10, y: 72 }
      })

      const container = document.getElementById(`${props.id}`)
      const width = container?.scrollWidth
      const height = container?.scrollHeight || 655
      graph = new G6.TreeGraph({
        container: container || `${props.id}`,
        width,
        height,
        plugins: [toolbar],
        modes: {
          default: ['drag-canvas']
        },
        defaultNode: {
          type: 'card-node',
          size: [200, 100]
        },
        defaultEdge: {
          type: 'cubic-horizontal',
          style: {
            endArrow: true
          }
        },
        layout: {
          type: 'indented',
          direction: 'LR',
          dropCap: false,
          indent: 250,
          getHeight: () => {
            return 100
          }
        }
      })

      graph.data(data.value)
      graph.render()
      graph.fitView()

      // 绑定结点事件
      graph.on('node:click', (e: any) => {
        if (e.target.get('name') === 'collapse-icon') {
          e.item.getModel().collapsed = !e.item.getModel().collapsed
          graph.setItemState(e.item, 'collapsed', e.item.getModel().collapsed)
          graph.layout()
        }
      })
      graph.on('node:contextmenu', (e: any) => {
        const model = e.item._cfg.model,
          data = model.data,
          type = data.type
        switch (type) {
          case 'module':
            createContentMenu(e, modelMenuConfig)
            break
          case 'container':
          case 'subContainer':
            if (
              data.isNew &&
              containerMenuConfig.findIndex(
                (item: any) => item.label === '删除'
              ) === -1
            ) {
              containerMenuConfig.push(contentMenuRemoveItem)
            }
            createContentMenu(e, containerMenuConfig)
            break
          case 'parameter':
            if (data.parameterType === 'enumeration') {
              if (
                data.isNew &&
                parameterMenuConfig_enum.findIndex(
                  (item: any) => item.label === '删除'
                ) === -1
              ) {
                parameterMenuConfig_enum.push(contentMenuRemoveItem)
              }
              createContentMenu(e, parameterMenuConfig_enum)
            } else if (data.parameterType === 'boolean') {
              if (
                data.isNew &&
                parameterMenuConfig_enum.findIndex(
                  (item: any) => item.label === '删除'
                ) === -1
              ) {
                parameterMenuConfig_enum.push(contentMenuRemoveItem)
              }
              createContentMenu(e, parameterMenuConfig_boolean)
            } else {
              if (
                data.isNew &&
                parameterMenuConfig.findIndex(
                  (item: any) => item.label === '删除'
                ) === -1
              ) {
                parameterMenuConfig.push(contentMenuRemoveItem)
              }
              createContentMenu(e, parameterMenuConfig)
            }
            break
          case 'reference':
            if (data.referenceType === 'choice') {
              if (
                data.isNew &&
                referenceMenuConfig_choice.findIndex(
                  (item: any) => item.label === '删除'
                ) === -1
              ) {
                referenceMenuConfig_choice.push(contentMenuRemoveItem)
              }
              createContentMenu(e, referenceMenuConfig_choice)
            } else {
              if (
                data.isNew &&
                referenceMenuConfig.findIndex(
                  (item: any) => item.label === '删除'
                ) === -1
              ) {
                referenceMenuConfig.push(contentMenuRemoveItem)
              }
              createContentMenu(e, referenceMenuConfig)
            }
            break
          case 'literal':
            if (
              data.isNew &&
              literalMenuConfig.findIndex(
                (item: any) => item.label === '删除'
              ) === -1
            ) {
              literalMenuConfig.push(contentMenuRemoveItem)
            }
            createContentMenu(e, literalMenuConfig)
            break
          default:
            if (data.isNew) {
              const temp: IMenuTemplate[] = []
              temp.push(contentMenuRemoveItem)
              createContentMenu(e, temp)
            }
            break
        }
        curr_data.value = model
        curr_data_id = model.id
        parent_data_id = model.parentId
      })
      graph.on('node:dblclick', (e: any) => {
        const model = e.item._cfg.model
        const type = model.data.type
        switch (type) {
          case 'module':
            openDialog_model(model)
            break
          case 'container':
          case 'subContainer':
            openDialog_container(model)
            break
          case 'parameter':
            openDialog_parameter(model)
            break
          case 'reference':
            openDialog_reference(model)
            break
          case 'literal':
            openDialog_literal(model)
            break
          default:
            break
        }
        curr_data.value = model
      })

      if (typeof window !== 'undefined') {
        window.onresize = () => {
          if (!graph || graph.get('destroyed')) return
          if (!container || !container.scrollWidth || !container.scrollHeight)
            return
          graph.changeSize(container.scrollWidth, container.scrollHeight)
        }
      }

      // 4. 总线事件绑定
      emitter.on('appendNextContainer', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'containerName',
              isNew: true,
              type: 'container',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          curr_data_id
        )
      })
      emitter.on('appendNextSubContainer', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'containerName',
              isNew: true,
              type: 'subContainer',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          curr_data_id
        )
      })
      emitter.on('appendNextParameter', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'parameterName',
              isNew: true,
              type: 'parameter',
              parameterType: '',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          curr_data_id
        )
      })
      emitter.on('appendNextReference', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'referenceName',
              isNew: true,
              type: 'reference',
              referenceType: '',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          curr_data_id
        )
      })
      emitter.on('appendContainer', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: parent_data_id,
            data: {
              label: 'containerName',
              isNew: true,
              type: 'container',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          parent_data_id
        )
      })
      emitter.on('addApiConfigDef', () => {
        openDialog_apiConfigDef()
        // ElMessageBox.close()
        // ElMessageBox({
        //   title: '提示',
        //   message: '确定添加配置参数吗？',
        //   confirmButtonText: '确定',
        //   cancelButtonText: '取消',
        //   type: 'warning',
        //   draggable: true,
        //   closeOnClickModal: false
        // })
        //   .then(() => {
        //     console.log(curr_data.value)
        //     emit('getApiConfigDef', curr_data.value.data.label)
        //     ElMessage({
        //       type: 'success',
        //       message: 'Delete completed'
        //     })
        //   })
        //   .catch(() => {
        //     ElMessage({
        //       type: 'info',
        //       message: 'Delete canceled'
        //     })
        //   })
      })
      emitter.on('addOtherConfigDef', () => {
        console.log(1)
      })
      emitter.on('appendParameter', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: parent_data_id,
            data: {
              label: 'parameterName',
              isNew: true,
              type: 'parameter',
              parameterType: data.value.parameterType,
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            },
            children: []
          },
          parent_data_id
        )
      })
      emitter.on('appendReference', () => {
        console.log(1)
      })
      emitter.on('appendNextLitiral', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'litiralName',
              isNew: true,
              type_: 'literal',
              description: '',
              lowerMultiplicity: '1',
              upperMultiplicity: '1'
            }
          },
          curr_data_id
        )
      })
      emitter.on('appendLiteral', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: parent_data_id,
            data: {
              label: 'litiralName',
              isNew: true,
              type: 'literal',
              description: '',
              lowerMultiplicity: '1',
              upperMultiplicity: '1'
            }
          },
          parent_data_id
        )
      })
      emitter.on('appendNextDestination', () => {
        graph.addChild(
          {
            id: String(new_id++),
            parentId: curr_data_id,
            data: {
              label: 'destinationName',
              isNew: true,
              type: 'destination',
              description: '',
              lowerMultiplicity: null,
              upperMultiplicity: null
            }
          },
          curr_data_id
        )
      })
      emitter.on('remove', () => {
        graph.removeChild(curr_data_id)
      })
      emitter.on('update', () => {
        graph.updateChild(data.value, 'root')
      })
    }

    // 4. hooks生成dialog的公共函数和参数
    const {
      dialogVisible: dialogVisible_model,
      newFormItem: newFormItem_model,
      openDialog: openDialog_model,
      closeDialog: closeDialog_model,
      handleConfirm: handleConfirm_model
    } = usePageDialogFormTree(data)

    const {
      dialogVisible: dialogVisible_container,
      newFormItem: newFormItem_container,
      openDialog: openDialog_container,
      closeDialog: closeDialog_container,
      handleConfirm: handleConfirm_container
    } = usePageDialogFormTree(data)

    const {
      dialogVisible: dialogVisible_parameter,
      newFormItem: newFormItem_parameter,
      openDialog: openDialog_parameter,
      closeDialog: closeDialog_parameter,
      handleConfirm: handleConfirm_parameter
    } = usePageDialogFormTree(data)

    const {
      dialogVisible: dialogVisible_reference,
      newFormItem: newFormItem_reference,
      openDialog: openDialog_reference,
      closeDialog: closeDialog_reference,
      handleConfirm: handleConfirm_reference
    } = usePageDialogFormTree(data)

    const {
      dialogVisible: dialogVisible_literal,
      newFormItem: newFormItem_literal,
      openDialog: openDialog_literal,
      closeDialog: closeDialog_literal,
      handleConfirm: handleConfirm_literal
    } = usePageDialogFormTree(data)

    const apiConfigDef = ref({
      name: '',
      value: ''
    })
    const dialogVisible_apiConfigDef = ref(false)
    const openDialog_apiConfigDef = () => {
      dialogVisible_apiConfigDef.value = true
      console.log(curr_data.value)
      apiConfigDef.value.name = curr_data.value.data.label
    }
    const closeDialog_apiConfigDef = () => {
      dialogVisible_apiConfigDef.value = false
    }
    const handleConfirm_apiConfigDef = () => {
      dialogVisible_apiConfigDef.value = false
      emit('getApiConfigDef', apiConfigDef.value)
    }

    watch(
      data.value.data,
      (n) => {
        console.log(111)
        emitter.emit('update-tab', 'emitter')
        emit('getTreeData', n)
      },
      { deep: true }
    )
    onMounted(() => {
      drawGraph()
    })

    return {
      curr_data,
      parameterType,
      dialogVisible_model,
      newFormItem_model,
      closeDialog_model,
      handleConfirm_model,
      addModelConfig,
      dialogVisible_container,
      newFormItem_container,
      closeDialog_container,
      handleConfirm_container,
      addContainerConfig,
      dialogVisible_parameter,
      newFormItem_parameter,
      closeDialog_parameter,
      handleConfirm_parameter,
      addParameterConfig,
      dialogVisible_reference,
      newFormItem_reference,
      closeDialog_reference,
      handleConfirm_reference,
      addReferenceConfig,
      dialogVisible_literal,
      newFormItem_literal,
      closeDialog_literal,
      handleConfirm_literal,
      dialogVisible_apiConfigDef,
      closeDialog_apiConfigDef,
      handleConfirm_apiConfigDef,
      apiConfigDef
    }
  }
})
</script>

<style scoped lang="less"></style>
